{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sequence-to-Sequence模型  \n",
    "<center><img src=\"seq2seq.jpg\" alt=\"FAO\" width=\"500\"></center> \n",
    "1.可用于机器翻译  \n",
    "2.文章摘要  \n",
    "3.对话机器人  \n",
    "4.中文分词  \n",
    "......"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -*- coding:utf-8 -*-\n",
    "import re\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "# \n",
    "text = open('msr_train_10.txt').read()\n",
    "text = text.split('\\n')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['“/s  人/b  们/e  常/s  说/s  生/b  活/e  是/s  一/s  部/s  教/b  科/m  书/e  ，/s  而/s  血/s  与/s  火/s  的/s  战/b  争/e  更/s  是/s  不/b  可/m  多/m  得/e  的/s  教/b  科/m  书/e  ，/s  她/s  确/b  实/e  是/s  名/b  副/m  其/m  实/e  的/s  ‘/s  我/s  的/s  大/b  学/e  ’/s  。/s  ',\n",
       " '“/s  心/s  静/s  渐/s  知/s  春/s  似/s  海/s  ，/s  花/s  深/s  每/s  觉/s  影/s  生/s  香/s  。/s  ',\n",
       " '“/s  吃/s  屎/s  的/s  东/b  西/e  ，/s  连/s  一/s  捆/s  麦/s  也/s  铡/s  不/s  动/s  呀/s  ？/s  ',\n",
       " '他/s  “/s  严/b  格/m  要/m  求/e  自/b  己/e  ，/s  从/s  一/b  个/e  科/b  举/e  出/b  身/e  的/s  进/b  士/e  成/b  为/e  一/b  个/e  伟/b  大/e  的/s  民/b  主/m  主/m  义/e  者/s  ，/s  进/b  而/e  成/b  为/e  一/s  位/s  杰/b  出/e  的/s  党/b  外/e  共/b  产/m  主/m  义/e  战/b  士/e  ，/s  献/b  身/e  于/s  崇/b  高/e  的/s  共/b  产/m  主/m  义/e  事/b  业/e  。/s  ',\n",
       " '“/s  征/s  而/s  未/s  用/s  的/s  耕/b  地/e  和/s  有/s  收/b  益/e  的/s  土/b  地/e  ，/s  不/b  准/e  荒/b  芜/e  。/s  ',\n",
       " '“/s  这/s  首/b  先/e  是/s  个/s  民/b  族/e  问/b  题/e  ，/s  民/b  族/e  的/s  感/b  情/e  问/b  题/e  。/s  ',\n",
       " '’/s  我/s  扔/s  了/s  两/b  颗/e  手/b  榴/m  弹/e  ，/s  他/s  一/b  下/m  子/e  出/s  溜/s  下/b  去/e  。/s  ',\n",
       " '“/s  废/b  除/e  先/b  前/e  存/b  在/e  的/s  所/b  有/m  制/e  关/b  系/e  ，/s  并/b  不/m  是/e  共/b  产/m  主/m  义/e  所/s  独/b  具/e  的/s  特/b  征/e  。/s  ',\n",
       " '“/s  这/b  个/e  案/b  子/e  从/s  始/s  至/b  今/e  我/b  们/e  都/s  没/b  有/e  跟/s  法/b  官/e  接/b  触/e  过/s  ，/s  也/s  没/b  有/e  跟/s  原/b  告/e  、/s  被/b  告/e  接/b  触/e  过/s  。/s  ',\n",
       " '“/s  你/s  只/b  有/e  把/s  事/b  情/e  做/b  好/e  ，/s  大/b  伙/e  才/s  服/s  你/s  。/s  ']"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# {B:begin, M:middle, E:end, S:single}，分别代表每个状态代表的是该字在词语中的位置，\n",
    "# B代表该字是词语中的起始字，M代表是词语中的中间字，E代表是词语中的结束字，S则代表是单字成词\n",
    "text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 设置参数\n",
    "# 词向量长度\n",
    "word_size = 128\n",
    "# 设置最长的一句话为32个字\n",
    "maxlen = 32\n",
    "# 批次大小\n",
    "batch_size = 1024\n",
    "\n",
    "# 根据符号分句\n",
    "text = u''.join( text)\n",
    "text = re.split(u'[，。！？、]/[bems]', text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "25"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['“/s  人/b  们/e  常/s  说/s  生/b  活/e  是/s  一/s  部/s  教/b  科/m  书/e  ',\n",
       " '  而/s  血/s  与/s  火/s  的/s  战/b  争/e  更/s  是/s  不/b  可/m  多/m  得/e  的/s  教/b  科/m  书/e  ',\n",
       " '  她/s  确/b  实/e  是/s  名/b  副/m  其/m  实/e  的/s  ‘/s  我/s  的/s  大/b  学/e  ’/s  ',\n",
       " '  “/s  心/s  静/s  渐/s  知/s  春/s  似/s  海/s  ',\n",
       " '  花/s  深/s  每/s  觉/s  影/s  生/s  香/s  ',\n",
       " '  “/s  吃/s  屎/s  的/s  东/b  西/e  ',\n",
       " '  连/s  一/s  捆/s  麦/s  也/s  铡/s  不/s  动/s  呀/s  ',\n",
       " '  他/s  “/s  严/b  格/m  要/m  求/e  自/b  己/e  ',\n",
       " '  从/s  一/b  个/e  科/b  举/e  出/b  身/e  的/s  进/b  士/e  成/b  为/e  一/b  个/e  伟/b  大/e  的/s  民/b  主/m  主/m  义/e  者/s  ',\n",
       " '  进/b  而/e  成/b  为/e  一/s  位/s  杰/b  出/e  的/s  党/b  外/e  共/b  产/m  主/m  义/e  战/b  士/e  ',\n",
       " '  献/b  身/e  于/s  崇/b  高/e  的/s  共/b  产/m  主/m  义/e  事/b  业/e  ',\n",
       " '  “/s  征/s  而/s  未/s  用/s  的/s  耕/b  地/e  和/s  有/s  收/b  益/e  的/s  土/b  地/e  ',\n",
       " '  不/b  准/e  荒/b  芜/e  ',\n",
       " '  “/s  这/s  首/b  先/e  是/s  个/s  民/b  族/e  问/b  题/e  ',\n",
       " '  民/b  族/e  的/s  感/b  情/e  问/b  题/e  ',\n",
       " '  ’/s  我/s  扔/s  了/s  两/b  颗/e  手/b  榴/m  弹/e  ',\n",
       " '  他/s  一/b  下/m  子/e  出/s  溜/s  下/b  去/e  ',\n",
       " '  “/s  废/b  除/e  先/b  前/e  存/b  在/e  的/s  所/b  有/m  制/e  关/b  系/e  ',\n",
       " '  并/b  不/m  是/e  共/b  产/m  主/m  义/e  所/s  独/b  具/e  的/s  特/b  征/e  ',\n",
       " '  “/s  这/b  个/e  案/b  子/e  从/s  始/s  至/b  今/e  我/b  们/e  都/s  没/b  有/e  跟/s  法/b  官/e  接/b  触/e  过/s  ',\n",
       " '  也/s  没/b  有/e  跟/s  原/b  告/e  ',\n",
       " '  被/b  告/e  接/b  触/e  过/s  ',\n",
       " '  “/s  你/s  只/b  有/e  把/s  事/b  情/e  做/b  好/e  ',\n",
       " '  大/b  伙/e  才/s  服/s  你/s  ',\n",
       " '  ']"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 训练集数据\n",
    "data = []\n",
    "# 标签\n",
    "label = []\n",
    "\n",
    "# 得到所有的数据和标签\n",
    "def get_data(s):\n",
    "    s = re.findall('(.)/(.)', s)\n",
    "    if s:\n",
    "        s = np.array(s)\n",
    "        # 返回数据和标签，0为数据，1为标签\n",
    "        return list(s[:,0]), list(s[:,1])\n",
    "\n",
    "for s in text:\n",
    "    d = get_data(s)\n",
    "    if d:\n",
    "        data.append(d[0])\n",
    "        label.append(d[1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('你', 's'),\n",
       " ('只', 'b'),\n",
       " ('有', 'e'),\n",
       " ('把', 's'),\n",
       " ('事', 'b'),\n",
       " ('情', 'e'),\n",
       " ('做', 'b'),\n",
       " ('好', 'e')]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test = re.findall('(.)/(.)', '你/s  只/b  有/e  把/s  事/b  情/e  做/b  好/e')\n",
    "test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义一个dataframe存放数据和标签\n",
    "d = pd.DataFrame(index=range(len(data)))\n",
    "d['data'] = data\n",
    "d['label'] = label\n",
    "# 提取data长度小于等于maxlen的数据\n",
    "d = d[d['data'].apply(len) <= maxlen]\n",
    "# 重新排列index\n",
    "d.index = range(len(d))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>data</th>\n",
       "      <th>label</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>[“, 人, 们, 常, 说, 生, 活, 是, 一, 部, 教, 科, 书]</td>\n",
       "      <td>[s, b, e, s, s, b, e, s, s, s, b, m, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>[而, 血, 与, 火, 的, 战, 争, 更, 是, 不, 可, 多, 得, 的, 教, ...</td>\n",
       "      <td>[s, s, s, s, s, b, e, s, s, b, m, m, e, s, b, ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>[她, 确, 实, 是, 名, 副, 其, 实, 的, ‘, 我, 的, 大, 学, ’]</td>\n",
       "      <td>[s, b, e, s, b, m, m, e, s, s, s, s, b, e, s]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>[“, 心, 静, 渐, 知, 春, 似, 海]</td>\n",
       "      <td>[s, s, s, s, s, s, s, s]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>[花, 深, 每, 觉, 影, 生, 香]</td>\n",
       "      <td>[s, s, s, s, s, s, s]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>[“, 吃, 屎, 的, 东, 西]</td>\n",
       "      <td>[s, s, s, s, b, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>[连, 一, 捆, 麦, 也, 铡, 不, 动, 呀]</td>\n",
       "      <td>[s, s, s, s, s, s, s, s, s]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>[他, “, 严, 格, 要, 求, 自, 己]</td>\n",
       "      <td>[s, s, b, m, m, e, b, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>[从, 一, 个, 科, 举, 出, 身, 的, 进, 士, 成, 为, 一, 个, 伟, ...</td>\n",
       "      <td>[s, b, e, b, e, b, e, s, b, e, b, e, b, e, b, ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>[进, 而, 成, 为, 一, 位, 杰, 出, 的, 党, 外, 共, 产, 主, 义, ...</td>\n",
       "      <td>[b, e, b, e, s, s, b, e, s, b, e, b, m, m, e, ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>[献, 身, 于, 崇, 高, 的, 共, 产, 主, 义, 事, 业]</td>\n",
       "      <td>[b, e, s, b, e, s, b, m, m, e, b, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>[“, 征, 而, 未, 用, 的, 耕, 地, 和, 有, 收, 益, 的, 土, 地]</td>\n",
       "      <td>[s, s, s, s, s, s, b, e, s, s, b, e, s, b, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>[不, 准, 荒, 芜]</td>\n",
       "      <td>[b, e, b, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>[“, 这, 首, 先, 是, 个, 民, 族, 问, 题]</td>\n",
       "      <td>[s, s, b, e, s, s, b, e, b, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>[民, 族, 的, 感, 情, 问, 题]</td>\n",
       "      <td>[b, e, s, b, e, b, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>[’, 我, 扔, 了, 两, 颗, 手, 榴, 弹]</td>\n",
       "      <td>[s, s, s, s, b, e, b, m, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>[他, 一, 下, 子, 出, 溜, 下, 去]</td>\n",
       "      <td>[s, b, m, e, s, s, b, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>[“, 废, 除, 先, 前, 存, 在, 的, 所, 有, 制, 关, 系]</td>\n",
       "      <td>[s, b, e, b, e, b, e, s, b, m, e, b, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>[并, 不, 是, 共, 产, 主, 义, 所, 独, 具, 的, 特, 征]</td>\n",
       "      <td>[b, m, e, b, m, m, e, s, b, e, s, b, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>[“, 这, 个, 案, 子, 从, 始, 至, 今, 我, 们, 都, 没, 有, 跟, ...</td>\n",
       "      <td>[s, b, e, b, e, s, s, b, e, b, e, s, b, e, s, ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>[也, 没, 有, 跟, 原, 告]</td>\n",
       "      <td>[s, b, e, s, b, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>21</th>\n",
       "      <td>[被, 告, 接, 触, 过]</td>\n",
       "      <td>[b, e, b, e, s]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>22</th>\n",
       "      <td>[“, 你, 只, 有, 把, 事, 情, 做, 好]</td>\n",
       "      <td>[s, s, b, e, s, b, e, b, e]</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>[大, 伙, 才, 服, 你]</td>\n",
       "      <td>[b, e, s, s, s]</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                 data  \\\n",
       "0             [“, 人, 们, 常, 说, 生, 活, 是, 一, 部, 教, 科, 书]   \n",
       "1   [而, 血, 与, 火, 的, 战, 争, 更, 是, 不, 可, 多, 得, 的, 教, ...   \n",
       "2       [她, 确, 实, 是, 名, 副, 其, 实, 的, ‘, 我, 的, 大, 学, ’]   \n",
       "3                            [“, 心, 静, 渐, 知, 春, 似, 海]   \n",
       "4                               [花, 深, 每, 觉, 影, 生, 香]   \n",
       "5                                  [“, 吃, 屎, 的, 东, 西]   \n",
       "6                         [连, 一, 捆, 麦, 也, 铡, 不, 动, 呀]   \n",
       "7                            [他, “, 严, 格, 要, 求, 自, 己]   \n",
       "8   [从, 一, 个, 科, 举, 出, 身, 的, 进, 士, 成, 为, 一, 个, 伟, ...   \n",
       "9   [进, 而, 成, 为, 一, 位, 杰, 出, 的, 党, 外, 共, 产, 主, 义, ...   \n",
       "10               [献, 身, 于, 崇, 高, 的, 共, 产, 主, 义, 事, 业]   \n",
       "11      [“, 征, 而, 未, 用, 的, 耕, 地, 和, 有, 收, 益, 的, 土, 地]   \n",
       "12                                       [不, 准, 荒, 芜]   \n",
       "13                     [“, 这, 首, 先, 是, 个, 民, 族, 问, 题]   \n",
       "14                              [民, 族, 的, 感, 情, 问, 题]   \n",
       "15                        [’, 我, 扔, 了, 两, 颗, 手, 榴, 弹]   \n",
       "16                           [他, 一, 下, 子, 出, 溜, 下, 去]   \n",
       "17            [“, 废, 除, 先, 前, 存, 在, 的, 所, 有, 制, 关, 系]   \n",
       "18            [并, 不, 是, 共, 产, 主, 义, 所, 独, 具, 的, 特, 征]   \n",
       "19  [“, 这, 个, 案, 子, 从, 始, 至, 今, 我, 们, 都, 没, 有, 跟, ...   \n",
       "20                                 [也, 没, 有, 跟, 原, 告]   \n",
       "21                                    [被, 告, 接, 触, 过]   \n",
       "22                        [“, 你, 只, 有, 把, 事, 情, 做, 好]   \n",
       "23                                    [大, 伙, 才, 服, 你]   \n",
       "\n",
       "                                                label  \n",
       "0             [s, b, e, s, s, b, e, s, s, s, b, m, e]  \n",
       "1   [s, s, s, s, s, b, e, s, s, b, m, m, e, s, b, ...  \n",
       "2       [s, b, e, s, b, m, m, e, s, s, s, s, b, e, s]  \n",
       "3                            [s, s, s, s, s, s, s, s]  \n",
       "4                               [s, s, s, s, s, s, s]  \n",
       "5                                  [s, s, s, s, b, e]  \n",
       "6                         [s, s, s, s, s, s, s, s, s]  \n",
       "7                            [s, s, b, m, m, e, b, e]  \n",
       "8   [s, b, e, b, e, b, e, s, b, e, b, e, b, e, b, ...  \n",
       "9   [b, e, b, e, s, s, b, e, s, b, e, b, m, m, e, ...  \n",
       "10               [b, e, s, b, e, s, b, m, m, e, b, e]  \n",
       "11      [s, s, s, s, s, s, b, e, s, s, b, e, s, b, e]  \n",
       "12                                       [b, e, b, e]  \n",
       "13                     [s, s, b, e, s, s, b, e, b, e]  \n",
       "14                              [b, e, s, b, e, b, e]  \n",
       "15                        [s, s, s, s, b, e, b, m, e]  \n",
       "16                           [s, b, m, e, s, s, b, e]  \n",
       "17            [s, b, e, b, e, b, e, s, b, m, e, b, e]  \n",
       "18            [b, m, e, b, m, m, e, s, b, e, s, b, e]  \n",
       "19  [s, b, e, b, e, s, s, b, e, b, e, s, b, e, s, ...  \n",
       "20                                 [s, b, e, s, b, e]  \n",
       "21                                    [b, e, b, e, s]  \n",
       "22                        [s, s, b, e, s, b, e, b, e]  \n",
       "23                                    [b, e, s, s, s]  "
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "#统计所有字，给每个字编号\n",
    "chars = [] \n",
    "for i in data:\n",
    "    chars.extend(i)\n",
    "\n",
    "chars = pd.Series(chars).value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "的    14\n",
       "“     9\n",
       "一     6\n",
       "是     5\n",
       "主     5\n",
       "     ..\n",
       "其     1\n",
       "静     1\n",
       "与     1\n",
       "始     1\n",
       "芜     1\n",
       "Length: 161, dtype: int64"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chars"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "的      1\n",
       "“      2\n",
       "一      3\n",
       "是      4\n",
       "主      5\n",
       "    ... \n",
       "其    157\n",
       "静    158\n",
       "与    159\n",
       "始    160\n",
       "芜    161\n",
       "Length: 161, dtype: int32"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chars[:] = range(1, len(chars)+1)\n",
    "chars"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "#生成适合模型输入的格式\n",
    "from tensorflow.python.keras.utils import np_utils\n",
    "\n",
    "# 定义标签所对应的编号\n",
    "tag = pd.Series({'s':0, 'b':1, 'm':2, 'e':3, 'x':4})\n",
    "\n",
    "# # 把中文变成编号，再补0\n",
    "# d['x'] = d['data'].apply(lambda x: np.array(list(chars[x])+[0]*(maxlen-len(x))))\n",
    "# # 把标签变成编号，再补0\n",
    "# d['y'] = d['label'].apply(lambda x: np.array(list(map(lambda y:np_utils.to_categorical(y,5), tag[x].reshape((-1,1))))+[np.array([[0,0,0,0,1]])]*(maxlen-len(x))))\n",
    "\n",
    "\n",
    "def data_helper(x):\n",
    "    x = list(chars[x]) + [0]*(maxlen-len(x))\n",
    "    return np.array(x)     \n",
    "\n",
    "def label_helper(x):\n",
    "    x = list(map(lambda y:np_utils.to_categorical(y,5), tag[x].values.reshape((-1,1))))\n",
    "    x = x + [np.array([[0,0,0,0,1]])]*(maxlen-len(x))\n",
    "    return np.array(x) \n",
    "    \n",
    "d['x'] = d['data'].apply(data_helper) \n",
    "d['y'] = d['label'].apply(label_helper)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['“', '人', '们', '常', '说', '生', '活', '是', '一', '部', '教', '科', '书']"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d['data'][0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  2, 135,  18,  57, 126,  29, 146,   4,   3,  52,  19,  11,  23,\n",
       "         0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,\n",
       "         0,   0,   0,   0,   0,   0])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d['x'][0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['s', 'b', 'e', 's', 's', 'b', 'e', 's', 's', 's', 'b', 'm', 'e']"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d['label'][0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[1., 0., 0., 0., 0.]],\n",
       "\n",
       "       [[0., 1., 0., 0., 0.]],\n",
       "\n",
       "       [[0., 0., 0., 1., 0.]],\n",
       "\n",
       "       [[1., 0., 0., 0., 0.]],\n",
       "\n",
       "       [[1., 0., 0., 0., 0.]],\n",
       "\n",
       "       [[0., 1., 0., 0., 0.]],\n",
       "\n",
       "       [[0., 0., 0., 1., 0.]],\n",
       "\n",
       "       [[1., 0., 0., 0., 0.]],\n",
       "\n",
       "       [[1., 0., 0., 0., 0.]],\n",
       "\n",
       "       [[1., 0., 0., 0., 0.]],\n",
       "\n",
       "       [[0., 1., 0., 0., 0.]],\n",
       "\n",
       "       [[0., 0., 1., 0., 0.]],\n",
       "\n",
       "       [[0., 0., 0., 1., 0.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]],\n",
       "\n",
       "       [[0., 0., 0., 0., 1.]]])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d['y'][0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<center><img src=\"lstm1.png\" alt=\"FAO\" width=\"500\"></center> \n",
    "<center><img src=\"lstm2.png\" alt=\"FAO\" width=\"500\"></center> "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "load model\n"
     ]
    }
   ],
   "source": [
    "# 设计模型\n",
    "from tensorflow.keras.layers import Dense, Embedding, LSTM, TimeDistributed, Input, Bidirectional\n",
    "from tensorflow.keras.models import Model\n",
    "from tensorflow.keras.models import load_model\n",
    "\n",
    "\n",
    "sequence = Input(shape=(maxlen,), dtype='int32')\n",
    "# 词汇数，词向量长度，输入的序列长度，是否忽略0值\n",
    "embedded = Embedding(len(chars)+1, word_size, input_length=maxlen, mask_zero=True)(sequence)\n",
    "# 双向RNN包装器\n",
    "blstm = Bidirectional(LSTM(64, return_sequences=True), merge_mode='sum')(embedded)\n",
    "# 该包装器可以把一个层应用到输入的每一个时间步上\n",
    "output = TimeDistributed(Dense(5, activation='softmax'))(blstm)\n",
    "# 定义模型输出输出\n",
    "model = Model(inputs=sequence, outputs=output)\n",
    "# 定义代价函数，优化器\n",
    "model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n",
    "\n",
    "\n",
    "# print(np.array(list(d['x'])).shape)\n",
    "# print(np.array(list(d['y'])).reshape((-1,maxlen,5)).shape)\n",
    "# model.fit(np.array(list(d['x'])), np.array(list(d['y'])).reshape((-1,maxlen,5)), batch_size=batch_size, epochs=20)\n",
    "# model.save('seq2seq.h5')\n",
    "\n",
    "print(\"load model\")\n",
    "model = load_model('seq2seq.h5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"model_1\"\n",
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "input_1 (InputLayer)         [(None, 32)]              0         \n",
      "_________________________________________________________________\n",
      "embedding_1 (Embedding)      (None, 32, 128)           660864    \n",
      "_________________________________________________________________\n",
      "bidirectional_1 (Bidirection (None, 32, 64)            98816     \n",
      "_________________________________________________________________\n",
      "time_distributed_1 (TimeDist (None, 32, 5)             325       \n",
      "=================================================================\n",
      "Total params: 760,005\n",
      "Trainable params: 760,005\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 做预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "import re\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "# 设置最长的一句话为32个字\n",
    "maxlen = 32\n",
    "\n",
    "# 使用全数据\n",
    "text = open('msr_train.txt').read()\n",
    "text = text.split('\\n')\n",
    "\n",
    "# 根据符号分句\n",
    "text = u''.join(text)\n",
    "text = re.split(u'[，。！？、]/[bems]', text)\n",
    "\n",
    "# 训练集数据\n",
    "data = []\n",
    "# 标签\n",
    "label = []\n",
    "\n",
    "# 得到所有的数据和标签\n",
    "def get_data(s):\n",
    "    s = re.findall('(.)/(.)', s)\n",
    "    if s:\n",
    "        s = np.array(s)\n",
    "        # 返回数据和标签，0为数据，1为标签\n",
    "        return list(s[:,0]), list(s[:,1])\n",
    "\n",
    "for s in text:\n",
    "    d = get_data(s)\n",
    "    if d:\n",
    "        data.append(d[0])\n",
    "        label.append(d[1])\n",
    "        \n",
    "# 定义一个dataframe存放数据和标签\n",
    "d = pd.DataFrame(index=range(len(data)))\n",
    "d['data'] = data\n",
    "d['label'] = label\n",
    "# 提取data长度小于等于maxlen的数据\n",
    "d = d[d['data'].apply(len) <= maxlen]\n",
    "# 重新排列index\n",
    "d.index = range(len(d))\n",
    "\n",
    "#统计所有字，给每个字编号\n",
    "chars = [] \n",
    "for i in data:\n",
    "    chars.extend(i)\n",
    "\n",
    "chars = pd.Series(chars).value_counts()\n",
    "chars[:] = range(1, len(chars)+1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "load model\n"
     ]
    }
   ],
   "source": [
    "from tensorflow.keras.models import load_model\n",
    "\n",
    "print(\"load model\")\n",
    "model = load_model('seq2seq.h5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'sb': 412351, 'be': 949884, 'es': 378288, 'ss': 266154, 'bm': 183969, 'me': 183974, 'mm': 170711, 'eb': 528062}\n"
     ]
    }
   ],
   "source": [
    "# 统计状态转移\n",
    "dict_label = {}\n",
    "for label in d['label']:\n",
    "    for i in range(len(label)-1):\n",
    "        tag = label[i] + label[i+1]\n",
    "        dict_label[tag] = dict_label.get(tag,0) + 1\n",
    "print(dict_label)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3073393"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 计算状态转移总次数\n",
    "sum_num = 0\n",
    "for value in dict_label.values():\n",
    "    sum_num = sum_num + value\n",
    "sum_num"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 计算状态转移概率\n",
    "p_ss = dict_label['ss']/sum_num\n",
    "p_sb = dict_label['sb']/sum_num\n",
    "p_bm = dict_label['bm']/sum_num\n",
    "p_be = dict_label['be']/sum_num\n",
    "p_mm = dict_label['mm']/sum_num\n",
    "p_me = dict_label['me']/sum_num\n",
    "p_es = dict_label['es']/sum_num\n",
    "p_eb = dict_label['eb']/sum_num"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 维特比算法，维特比算法是一种动态规划算法用于寻找最有可能产生观测事件序列的-维特比路径\n",
    "\n",
    "# tag = pd.Series({'s':0, 'b':1, 'm':2, 'e':3, 'x':4})\n",
    "\n",
    "# 00 = ss = 1\n",
    "# 01 = sb = 1\n",
    "# 02 = sm = 0\n",
    "# 03 = se = 0\n",
    "# 10 = bs = 0\n",
    "# 11 = bb = 0\n",
    "# 12 = bm = 1\n",
    "# 13 = be = 1\n",
    "# 20 = ms = 0\n",
    "# 21 = mb = 0\n",
    "# 22 = mm = 1\n",
    "# 23 = me = 1\n",
    "# 30 = es = 1\n",
    "# 31 = eb = 1\n",
    "# 32 = em = 0\n",
    "# 33 = ee = 0\n",
    "\n",
    "# 定义状态转移矩阵\n",
    "transfer = [[p_ss,p_sb,0,0],\n",
    "            [0,0,p_bm,p_be],\n",
    "            [0,0,p_mm,p_me],\n",
    "            [p_es,p_eb,0,0]]\n",
    "\n",
    "# # 定义状态转移矩阵\n",
    "# transfer = [[1,1,0,0],\n",
    "#             [0,0,1,1],\n",
    "#             [0,0,1,1],\n",
    "#             [1,1,0,0]]\n",
    "\n",
    "# 根据符号断句\n",
    "cuts = re.compile(u'([\\da-zA-Z ]+)|[。，、？！\\.\\?,!]')\n",
    "\n",
    "# 预测分词\n",
    "def predict(sentence):\n",
    "    \n",
    "    # 如果句子大于最大长度，只取maxlen个词\n",
    "    if len(sentence) > maxlen:\n",
    "        sentence = sentence[:maxlen]\n",
    "    \n",
    "    # 预测结果，先把句子变成编号的形式，如果出现生僻字就填充0，然后给句子补0直到maxlen的长度。预测得到的结果只保留跟句子有效数据相同的长度\n",
    "    result = model.predict(np.array([list(chars[list(sentence)].fillna(0).astype(int))+[0]*(maxlen-len(sentence))]))[0][:len(sentence)]\n",
    "\n",
    "    # 存放最终结果\n",
    "    y = []\n",
    "    # 存放临时概率值\n",
    "    prob = []\n",
    "    # 计算最大转移概率\n",
    "    # 首先计算第1个字和第2个字,统计16种情况的概率\n",
    "    # result[0][j]第1个词的标签概率\n",
    "    # result[1][k]第2个词的标签概率\n",
    "    # transfer[j][k]对应的转移概率矩阵的概率\n",
    "    for j in range(4):\n",
    "        for k in range(4):\n",
    "            # 第1个词为标签j的概率*第2个词为标签k的概率*jk的转移概率\n",
    "            prob.append(result[0][j]*result[1][k]*transfer[j][k])\n",
    "\n",
    "    # 计算前一个词的的标签\n",
    "    word1 = np.argmax(prob)//4\n",
    "    # 计算后一个词的标签\n",
    "    word2 = np.argmax(prob)%4\n",
    "    # 保存结果\n",
    "    y.append(word1)\n",
    "    y.append(word2)\n",
    "    # 从第2个字开始\n",
    "    for i in range(1,len(sentence)-1):\n",
    "        # 存放临时概率值\n",
    "        prob = []\n",
    "        # 计算前一个字和后一个字的所有转移概率\n",
    "        for j in range(4):\n",
    "            # 前一个字的标签已知为word2\n",
    "            prob.append(result[i][word2]*result[i+1][j]*transfer[word2][j])\n",
    "        # 计算后一个字的标签\n",
    "        word2 = np.argmax(prob)%4\n",
    "        # 保存结果\n",
    "        y.append(word2)\n",
    "        \n",
    "    # 分词\n",
    "    words = []\n",
    "    for i in range(len(sentence)):\n",
    "        # 如果标签为s或b，append到结果的list中\n",
    "        if y[i] in [0, 1]:\n",
    "            words.append(sentence[i])\n",
    "        else:\n",
    "        # 如果标签为m或e，在list最后一个元素中追加内容\n",
    "            words[-1] += sentence[i]\n",
    "    return words\n",
    "\n",
    "# 分句\n",
    "def cut_word(s):\n",
    "    result = []\n",
    "    # 指针设置为0\n",
    "    j = 0\n",
    "    # 根据符号断句\n",
    "    for i in cuts.finditer(s):\n",
    "        # 对符号前的部分分词\n",
    "        result.extend(predict(s[j:i.start()]))\n",
    "        # 加入符号\n",
    "        result.append(s[i.start():i.end()])\n",
    "        # 移动指针到符号后面\n",
    "        j = i.end()\n",
    "    # 对最后的部分进行分词\n",
    "    result.extend(predict(s[j:]))\n",
    "    return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['基于', 'seq2seq', '的', '中文', '分词器']"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cut_word('基于seq2seq的中文分词器')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['人们', '常说', '生活', '是', '一', '部', '教科书']"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cut_word('人们常说生活是一部教科书')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['广义', '相对论', '是', '描写', '物', '质间', '引力', '相互', '作用', '的', '理论']"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cut_word('广义相对论是描写物质间引力相互作用的理论')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['我', '爱', '北京', '天', '安', '门', '，', '天', '安', '门', '上', '太阳升']"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cut_word('我爱北京天安门，天安门上太阳升')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[5.3695281e-04, 9.9946302e-01, 2.5521592e-08, 4.3570454e-09,\n",
       "        1.4844584e-09],\n",
       "       [1.9184302e-04, 7.1967753e-07, 1.0082871e-06, 9.9980646e-01,\n",
       "        2.5343463e-09],\n",
       "       [1.1647545e-06, 9.9999511e-01, 3.7472587e-06, 4.4786855e-11,\n",
       "        1.2289153e-11],\n",
       "       [4.9465511e-05, 1.5763325e-10, 6.9671660e-04, 9.9925381e-01,\n",
       "        4.1510535e-11],\n",
       "       [9.9982244e-01, 1.7732647e-04, 1.8819689e-07, 1.0828031e-08,\n",
       "        5.8034683e-10],\n",
       "       [9.9905795e-01, 4.6581664e-07, 8.5055262e-08, 9.4140600e-04,\n",
       "        1.6101223e-08],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01],\n",
       "       [2.5680688e-01, 1.9268842e-01, 1.5925992e-01, 2.0500606e-01,\n",
       "        1.8623874e-01]], dtype=float32)"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.predict(np.array([list(chars[list('今天天气很好')].fillna(0).astype(int))+[0]*(maxlen-len('今天天气很好'))]))[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
